package com.sky.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.mybatis.mp.core.mybatis.mapper.context.Pager;
import cn.mybatis.mp.core.sql.executor.chain.QueryChain;
import com.sky.constant.MessageConstant;
import com.sky.dto.BorrowingHistoryQueryDTO;
import com.sky.dto.GetBorroweuestsDTO;
import com.sky.entity.*;
import com.sky.exception.BaseException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.EmailService;
import com.sky.service.UserBorrowhistoryService;
import com.sky.vo.BorrowingHistoryVO;
import com.sky.vo.GetUserBorrowVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserBorrowhistoryServiceImpl implements UserBorrowhistoryService {

    @Autowired
    private UserborrowhistoryMapper userborrowhistoryMapper;
    
    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private BooksMapper booksMapper;

    @Autowired
    private AdminsMapper adminsMapper;

    @Autowired
    private EmailService emailService;

    /**
     * 查询用户借阅历史信息
     *
     * @param getBorroweuestsDTO 分页查询参数
     * @return 用户借阅历史信息
     */
    public Pager<GetUserBorrowVO> getUserBorrow(GetBorroweuestsDTO getBorroweuestsDTO) {
        Users user = new Users();

        if (getBorroweuestsDTO.getUsername() != null && !getBorroweuestsDTO.getUsername().isEmpty()) {
            user = usersMapper.get(where -> {
                where.eq(Users::getUsername, getBorroweuestsDTO.getUsername());
            });
        }

        //获取借阅历史分页信息
        Pager<Userborrowhistory> userborrowhistoryPager = QueryChain.of(userborrowhistoryMapper)
                .ignoreEmptyInCondition(true)
                .ignoreNullValueInCondition(true)
                .trimStringInCondition(true)
                .like(user != null ? user.getUserId() != null : false, Borrowrequests::getUserId, Optional.ofNullable(user).map(Users::getUserId).map(Object::toString).orElse(null))
                .like(Userborrowhistory::getStatus, Optional.ofNullable(getBorroweuestsDTO.getStatus()).map(Object::toString).orElse(null))
                .paging(Pager.of(getBorroweuestsDTO.getPageNumber(), getBorroweuestsDTO.getPageSize()));

        //获取所有用户ID
        List<Integer> userIdList = userborrowhistoryPager.getResults().stream()
                .map(Userborrowhistory::getUserId)
                .collect(Collectors.toList());
        //获取所有图书ID
        List<Integer> bookIdList = userborrowhistoryPager.getResults().stream()
                .map(Userborrowhistory::getBookId)
                .collect(Collectors.toList());
        //获取所有管理员ID
        List<Integer> adminIdList = userborrowhistoryPager.getResults().stream()
                .map(Userborrowhistory::getAdminId)
                .collect(Collectors.toList());
        
        // 如果 userIdList 或 bookIdList 为空，直接返回空的分页结果
        if (userIdList.isEmpty() || bookIdList.isEmpty() || adminIdList.isEmpty()) {
            return new Pager<>();
        }

        // 批量查询用户姓名
        Map<Integer, String> usernameMap = usersMapper.selectBatchIds(userIdList)
                .stream()
                .collect(Collectors.toMap(Users::getUserId, Users::getUsername));
        // 批量查询用户姓名
        Map<Integer, String> bookNameMap = booksMapper.selectBatchIds(bookIdList)
                .stream()
                .collect(Collectors.toMap(Books::getBookId, Books::getTitle));
        //批量查询管理员姓名
        Map<Integer, String> adminNameMap = adminsMapper.selectBatchIds(adminIdList)
                .stream()
                .collect(Collectors.toMap(Admins::getAdminId, Admins::getUsername));

        List<GetUserBorrowVO> getUserBorrowVOList = userborrowhistoryPager.getResults().stream()
                .map(userborrowhistory -> {
                    GetUserBorrowVO vo = new GetUserBorrowVO();
                    vo.setBorrowHistoryId(userborrowhistory.getBorrowHistoryId());
                    vo.setUserId(userborrowhistory.getUserId());
                    vo.setUserId(userborrowhistory.getUserId());
                    vo.setUsername(usernameMap.getOrDefault(userborrowhistory.getUserId(), "未知用户")); // 设置用户名
                    vo.setBookId(userborrowhistory.getBookId());
                    vo.setTitle(bookNameMap.getOrDefault(userborrowhistory.getBookId(), "未知书籍")); // 设置书名
                    vo.setBorrowDate(userborrowhistory.getBorrowDate());
                    vo.setReturnDate(userborrowhistory.getReturnDate());
                    vo.setDueDate(userborrowhistory.getDueDate());
                    vo.setOverdueDays(userborrowhistory.getOverdueDays());
                    vo.setStatus(userborrowhistory.getStatus());
                    vo.setReviewDate(userborrowhistory.getReviewDate());
                    vo.setAdminId(userborrowhistory.getAdminId());
                    vo.setAdminName(adminNameMap.getOrDefault(userborrowhistory.getAdminId(), "未知管理员")); //设置管理员姓名
                    vo.setComments(userborrowhistory.getComments());
                    return vo;
                })
                .collect(Collectors.toList());
        
        //创建包含GetUserBorrowVO的对象
        Pager<GetUserBorrowVO> getUserBorrowVOPager = new Pager<>();
        getUserBorrowVOPager.setTotal(userborrowhistoryPager.getTotal());
        getUserBorrowVOPager.setNumber(userborrowhistoryPager.getNumber());
        getUserBorrowVOPager.setSize(userborrowhistoryPager.getSize());
        getUserBorrowVOPager.setResults(getUserBorrowVOList);

        return getUserBorrowVOPager;
    }

    /**
     * 发送逾期邮件
     *
     * @param borrowHistoryId 用户借阅历史订单ID
     */
    public void sendOverdueEmail(String borrowHistoryId) {
        //获取订单信息
        Userborrowhistory userborrowhistory = userborrowhistoryMapper.get(where -> {
            where.eq(Userborrowhistory::getBorrowHistoryId, borrowHistoryId);
        });

        //判断订单是否存在
        if (userborrowhistory == null) {
            throw new BaseException(MessageConstant.INFORMATION_DOESNT_EXIST);
        }

        //检查订单是否逾期
        if (userborrowhistory.getOverdueDays() == null) {
            throw new BaseException(MessageConstant.THE_ORDER_IS_NOT_OVERDUE);
        }

        // 获取用户信息
        Users user = usersMapper.get(where -> {
            where.eq(Users::getUserId, userborrowhistory.getUserId());
        });

        if (user == null || user.getEmail() == null) {
            throw new BaseException("用户信息不存在或邮箱未设置");
        }

        // 获取图书信息
        Books book = booksMapper.get(where -> {
            where.eq(Books::getBookId, userborrowhistory.getBookId());
        });

        if (book == null) {
            throw new BaseException("图书信息不存在");
        }

        // 格式化日期
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String borrowDate = dateFormat.format(userborrowhistory.getBorrowDate());
        String dueDate = dateFormat.format(userborrowhistory.getDueDate());
        String nowDate = dateFormat.format(new Date());

        // 发送邮件
        emailService.sendOverdueReminderEmail(
            user.getEmail(),           // 用户邮箱
            user.getUsername(),        // 用户名
            book.getTitle(),           // 书名
            borrowDate,                // 借阅日期
            dueDate,                   // 应还日期
            userborrowhistory.getOverdueDays(),  // 逾期天数
            nowDate                    // 当前日期
        );
    }

    /**
     * 获取用户借阅历史列表
     * @param queryDTO 查询条件
     * @return 分页结果
     */
    @Override
    public PageResult getBorrowingHistory(BorrowingHistoryQueryDTO queryDTO) {
        // 获取当前登录用户ID
        Integer userId = StpUtil.getLoginIdAsInt();

        // 获取借阅历史分页信息
        Pager<Userborrowhistory> pager = QueryChain.of(userborrowhistoryMapper)
                .ignoreEmptyInCondition(true)
                .ignoreNullValueInCondition(true)
                .trimStringInCondition(true)
                .eq(Userborrowhistory::getUserId, userId)
                .eq(queryDTO.getStatus() != null, Userborrowhistory::getStatus, queryDTO.getStatus())
                .gte(queryDTO.getStartDate() != null, Userborrowhistory::getBorrowDate, queryDTO.getStartDate())
                .lte(queryDTO.getEndDate() != null, Userborrowhistory::getBorrowDate, queryDTO.getEndDate())
                .orderByDesc(Userborrowhistory::getBorrowDate)
                .paging(Pager.of(queryDTO.getPageNumber(), queryDTO.getPageSize()));

        // 如果结果为空，直接返回空的分页结果
        if (pager.getResults().isEmpty()) {
            return new PageResult(0L, List.of());
        }

        // 获取所有图书ID
        List<Integer> bookIdList = pager.getResults().stream()
                .map(Userborrowhistory::getBookId)
                .collect(Collectors.toList());

        // 批量查询图书信息
        List<Books> bookList = booksMapper.selectBatchIds(bookIdList);
        Map<Integer, Books> bookMap = bookList.stream()
                .collect(Collectors.toMap(Books::getBookId, book -> book));

        // 如果有关键词，过滤不匹配的记录
        List<BorrowingHistoryVO> voList = pager.getResults().stream()
                .filter(history -> {
                    if (queryDTO.getKeyword() != null && !queryDTO.getKeyword().isEmpty()) {
                        Books book = bookMap.get(history.getBookId());
                        if (book == null) return false;
                        return book.getTitle().contains(queryDTO.getKeyword()) || 
                               book.getAuthor().contains(queryDTO.getKeyword());
                    }
                    return true;
                })
                .map(history -> {
                    BorrowingHistoryVO vo = new BorrowingHistoryVO();
                    vo.setId(history.getBorrowHistoryId());
                    vo.setBorrowDate(history.getBorrowDate());
                    vo.setReturnDate(history.getDueDate());
                    vo.setStatus(history.getStatus().toString());

                    // 设置图书信息
                    Books book = bookMap.get(history.getBookId());
                    if (book != null) {
                        vo.setBookTitle(book.getTitle());
                        vo.setAuthor(book.getAuthor());
                        vo.setCoverImage(book.getCoverImage());
                        vo.setDescription(book.getDescription());
                    }

                    return vo;
                })
                .collect(Collectors.toList());

        return new PageResult(pager.getTotal(), voList);
    }

    /**
     * 归还图书
     * @param borrowHistoryId 借阅历史记录ID
     */
    @Override
    @Transactional
    public void returnBook(String borrowHistoryId) {
        // 1. 获取借阅历史记录
        Userborrowhistory borrowHistory = userborrowhistoryMapper.get(where -> {
            where.eq(Userborrowhistory::getBorrowHistoryId, borrowHistoryId);
        });

        // 2. 验证借阅记录是否存在
        if (borrowHistory == null) {
            throw new BaseException(MessageConstant.BORROW_RECORD_NOT_FOUND);
        }

        // 3. 验证借阅记录状态是否为"借阅中"或"已逾期"
        String status = borrowHistory.getStatus().toString();
        if (!"借阅中".equals(status) && !"已逾期".equals(status)) {
            throw new BaseException(MessageConstant.CANNOT_RETURN_BOOK);
        }

        // 4. 获取图书信息
        Books book = booksMapper.get(where -> {
            where.eq(Books::getBookId, borrowHistory.getBookId());
        });

        if (book == null) {
            throw new BaseException(MessageConstant.BOOK_INFO_NOT_FOUND);
        }

        // 5. 更新图书库存
        book.setStockQuantity(book.getStockQuantity() + 1);
        booksMapper.update(book);

        // 6. 更新借阅历史记录
        borrowHistory.setStatus("已归还");
        borrowHistory.setReturnDate(new Date());
        borrowHistory.setAdminId((int) StpUtil.getLoginIdAsLong()); // 设置处理归还的管理员ID
        
        userborrowhistoryMapper.update(borrowHistory);

        log.info("图书归还成功 - 借阅历史ID: {}, 图书ID: {}, 用户ID: {}", 
                borrowHistoryId, borrowHistory.getBookId(), borrowHistory.getUserId());
    }
}
